{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Pinecone\n",
    "\n",
    "Pinecone은 고성능 벡터 데이터베이스로, AI 및 머신러닝 애플리케이션을 위한 효율적인 벡터 저장 및 검색 솔루션입니다. \n",
    "\n",
    "Pinecone, Chroma, Faiss와 같은 벡터 데이터베이스들을 비교해보겠습니다. \n",
    "\n",
    "**Pinecone의 장점**\n",
    "\n",
    "1. 확장성: 대규모 데이터셋에 대해 뛰어난 확장성을 제공합니다.\n",
    "   \n",
    "2. 관리 용이성: 완전 관리형 서비스로, 인프라 관리 부담이 적습니다.\n",
    "   \n",
    "3. 실시간 업데이트: 데이터의 실시간 삽입, 업데이트, 삭제가 가능합니다.\n",
    "   \n",
    "4. 고가용성: 클라우드 기반으로 높은 가용성과 내구성을 제공합니다.\n",
    "   \n",
    "5. API 친화적: RESTful/Python API를 통해 쉽게 통합할 수 있습니다.\n",
    "\n",
    "**Pinecone의 단점**\n",
    "\n",
    "1. 비용: Chroma나 Faiss에 비해 상대적으로 비용이 높을 수 있습니다.\n",
    "   \n",
    "2. 커스터마이징 제한: 완전 관리형 서비스이기 때문에 세부적인 커스터마이징에 제한이 있을 수 있습니다.\n",
    "   \n",
    "3. 데이터 위치: 클라우드에 데이터를 저장해야 하므로, 데이터 주권 문제가 있을 수 있습니다.\n",
    "\n",
    "Chroma나 Faiss와 비교했을 때:\n",
    "\n",
    "- Chroma/FAISS 오픈소스이며 로컬에서 실행 가능하여 초기 비용이 낮고 데이터 제어가 용이합니다. 커스터마이징의 자유도가 높습니다. 하지만 대규모 확장성 면에서는 Pinecone에 비해 제한적일 수 있습니다.\n",
    "\n",
    "선택은 프로젝트의 규모, 요구사항, 예산 등을 고려하여 결정해야 합니다. 대규모 프로덕션 환경에서는 Pinecone이 유리할 수 있지만, 소규모 프로젝트나 실험적인 환경에서는 Chroma나 Faiss가 더 적합할 수 있습니다.\n",
    "\n",
    "**참고**\n",
    "\n",
    "- [Pinecone 공식 홈페이지](https://docs.pinecone.io/integrations/langchain)\n",
    "- [Pinecone 랭체인](https://python.langchain.com/v0.2/docs/integrations/vectorstores/pinecone/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# API 키를 환경변수로 관리하기 위한 설정 파일\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "# API 키 정보 로드\n",
    "load_dotenv()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# LangSmith 추적을 설정합니다. https://smith.langchain.com\n",
    "# !pip install langchain-teddynote\n",
    "from langchain_teddynote import logging\n",
    "\n",
    "# 프로젝트 이름을 입력합니다.\n",
    "logging.langsmith(\"CH09-VectorStores\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 업데이트 안내\n",
    "\n",
    "아래의 기능은 커스텀 구현한 내용이므로 아래의 라이브러리를 반드시 업데이트 후 진행해야 합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 업데이트 명령어\n",
    "# !pip install -U langchain-teddynote"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 한글 처리를 위한 불용어 사전"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "한글 불용어 사전 가져오기 (추후 토크나이저에 사용)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.korean import stopwords\n",
    "\n",
    "# 한글 불용어 사전 불러오기 (불용어 사전 출처: https://www.ranks.nl/stopwords/korean)\n",
    "stopword = stopwords()\n",
    "stopword[:20]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 데이터 전처리\n",
    "\n",
    "아래는 일반 문서의 전처리 과정입니다. `ROOT_DIR` 하위에 있는 모든 `.pdf` 파일을 읽어와 `document_lsit` 에 저장합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.document_loaders import PyMuPDFLoader\n",
    "from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
    "import glob\n",
    "\n",
    "# 텍스트 분할\n",
    "text_splitter = RecursiveCharacterTextSplitter(chunk_size=300, chunk_overlap=50)\n",
    "\n",
    "split_docs = []\n",
    "\n",
    "# 텍스트 파일을 load -> List[Document] 형태로 변환\n",
    "files = sorted(glob.glob(\"data/*.pdf\"))\n",
    "\n",
    "for file in files:\n",
    "    loader = PyMuPDFLoader(file)\n",
    "    split_docs.extend(loader.load_and_split(text_splitter))\n",
    "\n",
    "# 문서 개수 확인\n",
    "len(split_docs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "split_docs[0].page_content"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pinecone 에 DB 저장하기 위한 문서 전처리를 수행합니다. 이 과정에서 `metadata_keys` 를 지정할 수 있습니다.\n",
    "\n",
    "추가로 metadata 를 태깅하고 싶은 경우 사전 처리 작업에서 미리 metadata 를 추가한 뒤 진행합니다.\n",
    "\n",
    "- `split_docs`: 문서 분할 결과를 담은 List[Document] 입니다.\n",
    "- `metadata_keys`: 문서에 추가할 metadata 키를 담은 List 입니다.\n",
    "- `min_length`: 문서의 최소 길이를 지정합니다. 이 길이보다 짧은 문서는 제외합니다.\n",
    "- `use_basename`: 소스 경로를 기준으로 파일명을 사용할지 여부를 지정합니다. 기본값은 `False` 입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# metadata 를 확인합니다.\n",
    "split_docs[0].metadata"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 문서의 전처리\n",
    "\n",
    "- 필요한 `metadata` 정보를 추출합니다.\n",
    "- 최소 길이 이상의 데이만 필터링 합니다.\n",
    "  \n",
    "- 문서의 `basename` 을 사용할지 여부를 지정합니다. 기본값은 `False` 입니다.\n",
    "  - 여기서 `basename` 이란 파일 경로의 가장 마지막 부분을 의미합니다. \n",
    "  - 예를 들어, `/Users/teddy/data/document.pdf` 의 경우 `document.pdf` 가 됩니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "split_docs[0].metadata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "split_docs[0].page_content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.community.pinecone import preprocess_documents\n",
    "\n",
    "contents, metadatas = preprocess_documents(\n",
    "    split_docs=split_docs,\n",
    "    metadata_keys=[\"source\", \"page\", \"author\"],\n",
    "    min_length=5,\n",
    "    use_basename=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# use_basename=True 일 때, source 키에 파일명만 저장됩니다.(디렉토리를 제외됩니다.)\n",
    "metadatas[\"source\"][:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# VectorStore 에 저장할 문서 확인\n",
    "contents[:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# VectorStore 에 저장할 metadata 확인\n",
    "metadatas.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# metadata 에서 source 를 확인합니다.\n",
    "metadatas[\"source\"][:5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 문서 개수 확인, 소스 개수 확인, 페이지 개수 확인\n",
    "len(contents), len(metadatas[\"source\"]), len(metadatas[\"page\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### API 키 발급\n",
    "\n",
    "- [링크](https://app.pinecone.io/)\n",
    "- 프로필 - Account - Projects - Starter - API keys - 발급\n",
    "\n",
    "`.env` 파일에 아래와 같이 추가합니다.\n",
    "\n",
    "```\n",
    "PINECONE_API_KEY=\"YOUR_PINECONE_API_KEY\"\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 새로운 VectorStore 인덱스 생성\n",
    "\n",
    "Pinecone 의 새로운 인덱스를 생성합니다.\n",
    "\n",
    "![pinecone-01.png](./images/pinecone-01.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pinecone 인덱스를 생성합니다.\n",
    "\n",
    "**주의사항**\n",
    "- `metric` 은 유사도 측정 방법을 지정합니다. 만약 HybridSearch 를 고려하고 있다면 `metric` 은 `dotproduct` 로 지정합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from langchain_teddynote.community.pinecone import create_index\n",
    "\n",
    "# Pinecone 인덱스 생성\n",
    "pc_index = create_index(\n",
    "    api_key=os.environ[\"PINECONE_API_KEY\"],\n",
    "    index_name=\"teddynote-db-index\",  # 인덱스 이름을 지정합니다.\n",
    "    dimension=4096,  # Embedding 차원과 맞춥니다. (OpenAIEmbeddings: 1536, UpstageEmbeddings: 4096)\n",
    "    metric=\"dotproduct\",  # 유사도 측정 방법을 지정합니다. (dotproduct, euclidean, cosine)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "아래는 **유료 Pod** 를 사용하는 예시입니다. **유료 Pod** 는 무료 Serverless Pod 대비 더 확장된 기능을 제공합니다.\n",
    "\n",
    "- 참고: https://docs.pinecone.io/guides/indexes/choose-a-pod-type-and-size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from langchain_teddynote.community.pinecone import create_index\n",
    "from pinecone import PodSpec\n",
    "\n",
    "# Pinecone 인덱스 생성\n",
    "pc_index = create_index(\n",
    "    api_key=os.environ[\"PINECONE_API_KEY\"],\n",
    "    index_name=\"teddynote-db-index2\",  # 인덱스 이름을 지정합니다.\n",
    "    dimension=4096,  # Embedding 차원과 맞춥니다. (OpenAIEmbeddings: 1536, UpstageEmbeddings: 4096)\n",
    "    metric=\"dotproduct\",  # 유사도 측정 방법을 지정합니다. (dotproduct, euclidean, cosine)\n",
    "    pod_spec=PodSpec(\n",
    "        environment=\"us-west1-gcp\", pod_type=\"p1.x1\", pods=1\n",
    "    ),  # 유료 Pod 사용\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sparse Encoder 생성\n",
    "\n",
    "- Sparse Encoder 를 생성합니다. \n",
    "- `Kiwi Tokenizer` 와 한글 불용어(stopwords) 처리를 수행합니다.\n",
    "- Sparse Encoder 를 활용하여 contents 를 학습합니다. 여기서 학습한 인코드는 VectorStore 에 문서를 저장할 때 Sparse Vector 를 생성할 때 활용합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.community.pinecone import (\n",
    "    create_sparse_encoder,\n",
    "    fit_sparse_encoder,\n",
    ")\n",
    "\n",
    "# 한글 불용어 사전 + Kiwi 형태소 분석기를 사용합니다.\n",
    "sparse_encoder = create_sparse_encoder(stopwords(), mode=\"kiwi\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sparse Encoder 에 Corpus 를 학습합니다.\n",
    "\n",
    "- `save_path`: Sparse Encoder 를 저장할 경로입니다. 추후에 `pickle` 형식으로 저장한 Sparse Encoder 를 불러와 Query 임베딩할 때 사용합니다. 따라서, 이를 저장할 경로를 지정합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sparse Encoder 를 사용하여 contents 를 학습\n",
    "saved_path = fit_sparse_encoder(\n",
    "    sparse_encoder=sparse_encoder, contents=contents, save_path=\"./sparse_encoder.pkl\"\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[선택사항] 아래는 나중에 학습하고 저장한 Sparse Encoder 를 다시 불러와야 할 때 사용하는 코드입니다.    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.community.pinecone import load_sparse_encoder\n",
    "\n",
    "# 추후에 학습된 sparse encoder 를 불러올 때 사용합니다.\n",
    "sparse_encoder = load_sparse_encoder(\"./sparse_encoder.pkl\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Pinecone: DB Index에 추가 (Upsert)\n",
    "\n",
    "![](./images/pinecone-02.png)\n",
    "\n",
    "- `context`: 문서의 내용입니다.\n",
    "- `page`: 문서의 페이지 번호입니다.\n",
    "- `source`: 문서의 출처입니다.\n",
    "- `values`: Embedder 를 통해 얻은 문서의 임베딩입니다.\n",
    "- `sparse values`: Sparse Encoder 를 통해 얻은 문서의 임베딩입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import OpenAIEmbeddings\n",
    "from langchain_upstage import UpstageEmbeddings\n",
    "\n",
    "# 임베딩 모델 생성\n",
    "openai_embeddings = OpenAIEmbeddings(model=\"text-embedding-3-large\")\n",
    "upstage_embeddings = UpstageEmbeddings(model=\"solar-embedding-1-large-passage\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "분산 처리를 하지 않고 배치 단위로 문서를 Upsert 합니다. 문서의 양이 많지 않다면 아래의 방식을 사용하세요."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "from langchain_teddynote.community.pinecone import upsert_documents\n",
    "from langchain_upstage import UpstageEmbeddings\n",
    "\n",
    "upsert_documents(\n",
    "    index=pc_index,  # Pinecone 인덱스\n",
    "    namespace=\"teddynote-namespace-01\",  # Pinecone namespace\n",
    "    contents=contents,  # 이전에 전처리한 문서 내용\n",
    "    metadatas=metadatas,  # 이전에 전처리한 문서 메타데이터\n",
    "    sparse_encoder=sparse_encoder,  # Sparse encoder\n",
    "    embedder=upstage_embeddings,\n",
    "    batch_size=32,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "아래는 분산처리를 수행하여 대용량 문서를 빠르게 Upsert 합니다. 대용량 업로드시 활용하세요."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "from langchain_teddynote.community.pinecone import upsert_documents_parallel\n",
    "\n",
    "upsert_documents_parallel(\n",
    "    index=pc_index,  # Pinecone 인덱스\n",
    "    namespace=\"teddynote-namespace-02\",  # Pinecone namespace\n",
    "    contents=contents,  # 이전에 전처리한 문서 내용\n",
    "    metadatas=metadatas,  # 이전에 전처리한 문서 메타데이터\n",
    "    sparse_encoder=sparse_encoder,  # Sparse encoder\n",
    "    embedder=upstage_embeddings,\n",
    "    batch_size=64,\n",
    "    max_workers=30,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 인덱스 조회/삭제\n",
    "\n",
    "`describe_index_stats` 메서드는 인덱스의 내용에 대한 통계 정보를 제공합니다. 이 메서드를 통해 네임스페이스별 벡터 수와 차원 수 등의 정보를 얻을 수 있습니다.\n",
    "\n",
    "**매개변수**\n",
    "* `filter` (Optional[Dict[str, Union[str, float, int, bool, List, dict]]]): 특정 조건에 맞는 벡터들에 대한 통계만 반환하도록 하는 필터. 기본값은 None\n",
    "* `**kwargs`: 추가 키워드 인자\n",
    "\n",
    "**반환값**\n",
    "* `DescribeIndexStatsResponse`: 인덱스에 대한 통계 정보를 담고 있는 객체\n",
    "\n",
    "**사용 예시**\n",
    "* 기본 사용: `index.describe_index_stats()`\n",
    "* 필터 적용: `index.describe_index_stats(filter={'key': 'value'})`\n",
    "\n",
    "**참고**\n",
    "- metadata 필터링은 유료 사용자에 한하여 가능합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 인덱스 조회\n",
    "pc_index.describe_index_stats()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 네임스페이스(namespace) 삭제"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.community.pinecone import delete_namespace\n",
    "\n",
    "delete_namespace(\n",
    "    pinecone_index=pc_index,\n",
    "    namespace=\"teddynote-namespace-01\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pc_index.describe_index_stats()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "아래는 유료 사용자 전용 기능입니다. 유료 사용자는 metadata 필터링을 사용할 수 있습니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.community.pinecone import delete_by_filter\n",
    "\n",
    "# metadata 필터링(유료 기능) 으로 삭제\n",
    "delete_by_filter(\n",
    "    pinecone_index=pc_index,\n",
    "    namespace=\"teddynote-namespace-02\",\n",
    "    filter={\"source\": {\"$eq\": \"SPRi AI Brief_8월호_산업동향.pdf\"}},\n",
    ")\n",
    "pc_index.describe_index_stats()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 검색기(Retriever) 생성\n",
    "\n",
    "### PineconeKiwiHybridRetriever 초기화 파라미터 설정\n",
    "\n",
    "`init_pinecone_index` 함수와 `PineconeKiwiHybridRetriever` 클래스는 Pinecone을 사용한 하이브리드 검색 시스템을 구현합니다. 이 시스템은 밀집 벡터와 희소 벡터를 결합하여 효과적인 문서 검색을 수행합니다.\n",
    "\n",
    "**Pinecone 인덱스 초기화**\n",
    "\n",
    "`init_pinecone_index` 함수는 Pinecone 인덱스를 초기화하고 필요한 구성 요소를 설정합니다.\n",
    "\n",
    "**매개변수**\n",
    "* `index_name` (str): Pinecone 인덱스 이름\n",
    "* `namespace` (str): 사용할 네임스페이스\n",
    "* `api_key` (str): Pinecone API 키\n",
    "* `sparse_encoder_pkl_path` (str): 희소 인코더 피클 파일 경로\n",
    "* `stopwords` (List[str]): 불용어 리스트\n",
    "* `tokenizer` (str): 사용할 토크나이저 (기본값: \"kiwi\")\n",
    "* `embeddings` (Embeddings): 임베딩 모델\n",
    "* `top_k` (int): 반환할 최대 문서 수 (기본값: 10)\n",
    "* `alpha` (float): 밀집 벡터와 희소 벡터의 가중치 조절 파라미터 (기본값: 0.5)\n",
    "\n",
    "**주요 기능**\n",
    "1. Pinecone 인덱스 초기화 및 통계 정보 출력\n",
    "2. 희소 인코더(BM25) 로딩 및 토크나이저 설정\n",
    "3. 네임스페이스 지정"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# !pip install -U pinecone langchain-teddynote"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[init_pinecone_index]\n",
      "{'dimension': 4096,\n",
      " 'index_fullness': 0.0,\n",
      " 'namespaces': {'teddynote-namespace-02': {'vector_count': 1291}},\n",
      " 'total_vector_count': 1291}\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "from langchain_teddynote.korean import stopwords\n",
    "from langchain_teddynote.community.pinecone import init_pinecone_index\n",
    "from langchain_upstage import UpstageEmbeddings\n",
    "\n",
    "pinecone_params = init_pinecone_index(\n",
    "    index_name=\"teddynote-db-index\",  # Pinecone 인덱스 이름\n",
    "    namespace=\"teddynote-namespace-02\",  # Pinecone Namespace\n",
    "    api_key=os.environ[\"PINECONE_API_KEY\"],  # Pinecone API Key\n",
    "    sparse_encoder_path=\"./sparse_encoder.pkl\",  # Sparse Encoder 저장경로(save_path)\n",
    "    stopwords=stopwords(),  # 불용어 사전\n",
    "    tokenizer=\"kiwi\",\n",
    "    embeddings=UpstageEmbeddings(\n",
    "        model=\"solar-embedding-1-large-query\"\n",
    "    ),  # Dense Embedder\n",
    "    top_k=5,  # Top-K 문서 반환 개수\n",
    "    alpha=0.5,  # alpha=0.75로 설정한 경우, (0.75: Dense Embedding, 0.25: Sparse Embedding)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### PineconeKiwiHybridRetriever\n",
    "\n",
    "`PineconeKiwiHybridRetriever` 클래스는 Pinecone과 Kiwi를 결합한 하이브리드 검색기를 구현합니다.\n",
    "\n",
    "**주요 속성**\n",
    "* `embeddings`: 밀집 벡터 변환용 임베딩 모델\n",
    "* `sparse_encoder`: 희소 벡터 변환용 인코더\n",
    "* `index`: Pinecone 인덱스 객체\n",
    "* `top_k`: 반환할 최대 문서 수\n",
    "* `alpha`: 밀집 벡터와 희소 벡터의 가중치 조절 파라미터\n",
    "* `namespace`: Pinecone 인덱스 내 네임스페이스\n",
    "\n",
    "**특징**\n",
    "* 밀집 벡터와 희소 벡터를 결합한 HybridSearch Retriever\n",
    "* 가중치 조절을 통한 검색 전략 최적화 가능\n",
    "* 다양한 동적 metadata 필터링 적용 가능(`search_kwargs` 사용: `filter`, `k`, `rerank`, `rerank_model`, `top_n` 등)\n",
    "\n",
    "**사용 예시**\n",
    "1. `init_pinecone_index` 함수로 필요한 구성 요소 초기화\n",
    "2. 초기화된 구성 요소로 `PineconeKiwiHybridRetriever` 인스턴스 생성\n",
    "3. 생성된 검색기를 사용하여 하이브리드 검색 수행"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`PineconeKiwiHybridRetriever` 를 생성합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_teddynote.community.pinecone import PineconeKiwiHybridRetriever\n",
    "\n",
    "# 검색기 생성\n",
    "pinecone_retriever = PineconeKiwiHybridRetriever(**pinecone_params)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "일반 검색"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\n",
      "KEY Contents\n",
      "£ GPT-4o 미니, GPT-3.5 터보 대비 60% 이상 저렴하면서 성능은 우수\n",
      "n 오픈AI는 2024년 7월 28일 가장 비용 효율적인 소형 모델인 ‘GPT-4o 미니’를 출시하고 챗GPT에서 \n",
      "GPT-3.5를 대신해 무료 사용자 및 플러스와 팀 사용자에게 제공한다고 발표\n",
      "∙GPT-4o 미니는 입력 토큰 100만 개당 15센트, 출력 토큰 100만 개당 60센트로 가격이 책정되어, \n",
      "GPT-3.5 터보 대비 60% 이상 저렴\n",
      "{'author': 'dj', 'context': '앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\\nKEY Contents\\n£ GPT-4o 미니, GPT-3.5 터보 대비 60% 이상 저렴하면서 성능은 우수\\nn 오픈AI는 2024년 7월 28일 가장 비용 효율적인 소형 모델인 ‘GPT-4o 미니’를 출시하고 챗GPT에서 \\nGPT-3.5를 대신해 무료 사용자 및 플러스와 팀 사용자에게 제공한다고 발표\\n∙GPT-4o 미니는 입력 토큰 100만 개당 15센트, 출력 토큰 100만 개당 60센트로 가격이 책정되어, \\nGPT-3.5 터보 대비 60% 이상 저렴', 'page': 13.0, 'source': 'SPRi AI Brief_8월호_산업동향.pdf'}\n",
      "\n",
      "====================\n",
      "\n",
      "1. 정책/법제  \n",
      "2. 기업/산업 \n",
      "3. 기술/연구 \n",
      " 4. 인력/교육\n",
      "11\n",
      "오픈AI, 비용 효율적인 소형 AI 모델 ‘GPT-4o 미니’ 출시\n",
      "n 오픈AI가 GPT-3.5 터보 대비 60% 이상 저렴한 소형 모델 ‘GPT-4o’ 미니를 발표했으며, 저렴한 \n",
      "비용과 낮은 지연 시간으로 다양한 애플리케이션에 활용될 것으로 기대\n",
      "n GPT-4o는 주요 벤치마크에서 GPT-3.5를 앞섰으며, 경쟁 소형 모델인 구글의 제미나이 플래시와 \n",
      "앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\n",
      "KEY Contents\n",
      "{'author': 'dj', 'context': '1. 정책/법제  \\n2. 기업/산업 \\n3. 기술/연구 \\n 4. 인력/교육\\n11\\n오픈AI, 비용 효율적인 소형 AI 모델 ‘GPT-4o 미니’ 출시\\nn 오픈AI가 GPT-3.5 터보 대비 60% 이상 저렴한 소형 모델 ‘GPT-4o’ 미니를 발표했으며, 저렴한 \\n비용과 낮은 지연 시간으로 다양한 애플리케이션에 활용될 것으로 기대\\nn GPT-4o는 주요 벤치마크에서 GPT-3.5를 앞섰으며, 경쟁 소형 모델인 구글의 제미나이 플래시와 \\n앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\\nKEY Contents', 'page': 13.0, 'source': 'SPRi AI Brief_8월호_산업동향.pdf'}\n",
      "\n",
      "====================\n",
      "\n",
      "대화 기록)를 전달하는 작업, 실시간 고객 지원 챗봇 등 다양한 작업을 처리 가능\n",
      "∙오픈AI는 GPT-4o 미니를 통해 훨씬 저렴한 비용으로 AI를 이용할 수 있게 됨으로써 AI 애플리케이션 \n",
      "범위가 크게 확장될 것으로 기대\n",
      "n GPT-4o 미니는 뛰어난 텍스트 성능과 다중모드 추론을 지원하여 주요 벤치마크에서 GPT-4o에는 \n",
      "미달하지만 GPT-3.5 터보와 기타 소형 모델을 능가하는 결과를 기록\n",
      "∙GPT-4o 미니는 텍스트 지능과 추론 벤치마크인 MMLU에서 82.0%의 점수로 제미나이\n",
      "{'author': 'dj', 'context': '대화 기록)를 전달하는 작업, 실시간 고객 지원 챗봇 등 다양한 작업을 처리 가능\\n∙오픈AI는 GPT-4o 미니를 통해 훨씬 저렴한 비용으로 AI를 이용할 수 있게 됨으로써 AI 애플리케이션 \\n범위가 크게 확장될 것으로 기대\\nn GPT-4o 미니는 뛰어난 텍스트 성능과 다중모드 추론을 지원하여 주요 벤치마크에서 GPT-4o에는 \\n미달하지만 GPT-3.5 터보와 기타 소형 모델을 능가하는 결과를 기록\\n∙GPT-4o 미니는 텍스트 지능과 추론 벤치마크인 MMLU에서 82.0%의 점수로 제미나이', 'page': 13.0, 'source': 'SPRi AI Brief_8월호_산업동향.pdf'}\n",
      "\n",
      "====================\n",
      "\n",
      "▹ 오픈AI, 비용 효율적인 소형 AI 모델 ‘GPT-4o 미니’ 출시············································· 11\n",
      "   ▹ 바이두, 최신 AI 모델 ‘어니 4.0 터보’ 공개 ···································································· 12\n",
      "   ▹ 중국 상하이市 법학회, 세계인공지능대회에서 휴머노이드 로봇 거버넌스 지침 발표 ···· 13\n",
      "{'author': 'dj', 'context': '▹ 오픈AI, 비용 효율적인 소형 AI 모델 ‘GPT-4o 미니’ 출시············································· 11\\n   ▹ 바이두, 최신 AI 모델 ‘어니 4.0 터보’ 공개 ···································································· 12\\n   ▹ 중국 상하이市 법학회, 세계인공지능대회에서 휴머노이드 로봇 거버넌스 지침 발표 ···· 13', 'page': 1.0, 'source': 'SPRi AI Brief_8월호_산업동향.pdf'}\n",
      "\n",
      "====================\n",
      "\n",
      "£ ‘그록-2’, GPT-4o와 제미나이 프로 1.5 등 첨단 모델과 대등한 성능 \n",
      "n 일론 머스크(Elon Musk)가 설립한 AI 기업 xAI가 2024년 8월 13일 최첨단 추론 기능을 갖춘 \n",
      "‘그록(Grok)-2’와 이를 경량화한 ‘그록-2 미니’를 베타 버전으로 출시\n",
      "∙프리뷰 버전으로 출시된 두 모델은 X 프리미엄 구독자에게 제공되며 2024년 8월 말부터 \n",
      "엔터프라이즈 API를 통해서도 제공될 예정\n",
      "∙그록-2와 그록-2 미니는 대학원 수준의 과학 지식(GPQA)*, 일반 지식(MMLU, MMLU-Pro) 및\n",
      "{'author': 'dj', 'context': '£ ‘그록-2’, GPT-4o와 제미나이 프로 1.5 등 첨단 모델과 대등한 성능 \\nn 일론 머스크(Elon Musk)가 설립한 AI 기업 xAI가 2024년 8월 13일 최첨단 추론 기능을 갖춘 \\n‘그록(Grok)-2’와 이를 경량화한 ‘그록-2 미니’를 베타 버전으로 출시\\n∙프리뷰 버전으로 출시된 두 모델은 X 프리미엄 구독자에게 제공되며 2024년 8월 말부터 \\n엔터프라이즈 API를 통해서도 제공될 예정\\n∙그록-2와 그록-2 미니는 대학원 수준의 과학 지식(GPQA)*, 일반 지식(MMLU, MMLU-Pro) 및', 'page': 12.0, 'source': 'SPRi AI Brief_9월호_산업동향_F.pdf'}\n",
      "\n",
      "====================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 실행 결과\n",
    "search_results = pinecone_retriever.invoke(\"gpt-4o 미니 출시 관련 정보에 대해서 알려줘\")\n",
    "for result in search_results:\n",
    "    print(result.page_content)\n",
    "    print(result.metadata)\n",
    "    print(\"\\n====================\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "동적 `search_kwargs` 사용\n",
    "- `k`: 반환할 최대 문서 수 지정"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\n",
      "KEY Contents\n",
      "£ GPT-4o 미니, GPT-3.5 터보 대비 60% 이상 저렴하면서 성능은 우수\n",
      "n 오픈AI는 2024년 7월 28일 가장 비용 효율적인 소형 모델인 ‘GPT-4o 미니’를 출시하고 챗GPT에서 \n",
      "GPT-3.5를 대신해 무료 사용자 및 플러스와 팀 사용자에게 제공한다고 발표\n",
      "∙GPT-4o 미니는 입력 토큰 100만 개당 15센트, 출력 토큰 100만 개당 60센트로 가격이 책정되어, \n",
      "GPT-3.5 터보 대비 60% 이상 저렴\n",
      "{'author': 'dj', 'context': '앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\\nKEY Contents\\n£ GPT-4o 미니, GPT-3.5 터보 대비 60% 이상 저렴하면서 성능은 우수\\nn 오픈AI는 2024년 7월 28일 가장 비용 효율적인 소형 모델인 ‘GPT-4o 미니’를 출시하고 챗GPT에서 \\nGPT-3.5를 대신해 무료 사용자 및 플러스와 팀 사용자에게 제공한다고 발표\\n∙GPT-4o 미니는 입력 토큰 100만 개당 15센트, 출력 토큰 100만 개당 60센트로 가격이 책정되어, \\nGPT-3.5 터보 대비 60% 이상 저렴', 'page': 13.0, 'source': 'SPRi AI Brief_8월호_산업동향.pdf'}\n",
      "\n",
      "====================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 실행 결과\n",
    "search_results = pinecone_retriever.invoke(\n",
    "    \"gpt-4o 미니 출시 관련 정보에 대해서 알려줘\", search_kwargs={\"k\": 1}\n",
    ")\n",
    "for result in search_results:\n",
    "    print(result.page_content)\n",
    "    print(result.metadata)\n",
    "    print(\"\\n====================\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "동적 `search_kwargs` 사용\n",
    "- `alpha`: 밀집 벡터와 희소 벡터의 가중치 조절 파라미터. 0과 1 사이의 값을 지정합니다. `0.5` 가 기본값이고, 1에 가까울수록 dense 벡터의 가중치가 높아집니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "n 앤스로픽은 개발자 콘솔도 업데이트하여, 개발자가 여러 프롬프트를 생성하고 테스트함으로써 \n",
      "클로드를 최적화할 수 있도록 지원\n",
      "∙앤스로픽은 사용자가 클로드에 맞춤형 지침을 제공할 수 있는 ‘시스템 프롬프트’ 기능도 도입할 \n",
      "예정으로, 이 기능은 클로드가 사용자 요구에 맞춤화된 방식으로 체계적 응답을 할 수 있도록 지원\n",
      "☞ 출처 : Anthropic, Introducing Claude 2.1, 2023.11.21.\n",
      "{'author': 'dj', 'context': 'n 앤스로픽은 개발자 콘솔도 업데이트하여, 개발자가 여러 프롬프트를 생성하고 테스트함으로써 \\n클로드를 최적화할 수 있도록 지원\\n∙앤스로픽은 사용자가 클로드에 맞춤형 지침을 제공할 수 있는 ‘시스템 프롬프트’ 기능도 도입할 \\n예정으로, 이 기능은 클로드가 사용자 요구에 맞춤화된 방식으로 체계적 응답을 할 수 있도록 지원\\n☞ 출처 : Anthropic, Introducing Claude 2.1, 2023.11.21.', 'page': 7.0, 'source': 'SPRi AI Brief_2024년1월호_F.pdf'}\n",
      "\n",
      "====================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 실행 결과\n",
    "search_results = pinecone_retriever.invoke(\n",
    "    \"앤스로픽\", search_kwargs={\"alpha\": 1, \"k\": 1}\n",
    ")\n",
    "for result in search_results:\n",
    "    print(result.page_content)\n",
    "    print(result.metadata)\n",
    "    print(\"\\n====================\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. 정책/법제  \n",
      "2. 기업/산업 \n",
      "3. 기술/연구 \n",
      " 4. 인력/교육\n",
      "구글, 앤스로픽에 20억 달러 투자로 생성 AI 협력 강화 \n",
      "n 구글이 앤스로픽에 최대 20억 달러 투자에 합의하고 5억 달러를 우선 투자했으며, 앤스로픽은 \n",
      "구글과 클라우드 서비스 사용 계약도 체결\n",
      "n 3대 클라우드 사업자인 구글, 마이크로소프트, 아마존은 차세대 AI 모델의 대표 기업인 \n",
      "앤스로픽 및 오픈AI와 협력을 확대하는 추세\n",
      "KEY Contents\n",
      "£ 구글, 앤스로픽에 최대 20억 달러 투자 합의 및 클라우드 서비스 제공\n",
      "{'author': 'dj', 'context': '1. 정책/법제  \\n2. 기업/산업 \\n3. 기술/연구 \\n 4. 인력/교육\\n구글, 앤스로픽에 20억 달러 투자로 생성 AI 협력 강화 \\nn 구글이 앤스로픽에 최대 20억 달러 투자에 합의하고 5억 달러를 우선 투자했으며, 앤스로픽은 \\n구글과 클라우드 서비스 사용 계약도 체결\\nn 3대 클라우드 사업자인 구글, 마이크로소프트, 아마존은 차세대 AI 모델의 대표 기업인 \\n앤스로픽 및 오픈AI와 협력을 확대하는 추세\\nKEY Contents\\n£ 구글, 앤스로픽에 최대 20억 달러 투자 합의 및 클라우드 서비스 제공', 'page': 13.0, 'source': 'SPRI_AI_Brief_2023년12월호_F.pdf'}\n",
      "\n",
      "====================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 실행 결과\n",
    "search_results = pinecone_retriever.invoke(\n",
    "    \"앤스로픽\", search_kwargs={\"alpha\": 0, \"k\": 1}\n",
    ")\n",
    "for result in search_results:\n",
    "    print(result.page_content)\n",
    "    print(result.metadata)\n",
    "    print(\"\\n====================\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Metadata 필터링**\n",
    "\n",
    "![](./images/pinecone-metadata.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "동적 `search_kwargs` 사용\n",
    "- `filter`: metadata 필터링 적용\n",
    "\n",
    "(예시) `page` 가 5보다 작은 문서만 검색합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "▹ 앤스로픽, 최신 AI 모델 ‘클로드 3.5 소네트’ 출시··························································· 10\n",
      "   ▹ 프랑스의 미스트랄AI, 6억 유로 규모의 투자 유치  ························································ 11\n",
      "{'author': 'dj', 'context': '▹ 앤스로픽, 최신 AI 모델 ‘클로드 3.5 소네트’ 출시··························································· 10\\n   ▹ 프랑스의 미스트랄AI, 6억 유로 규모의 투자 유치  ························································ 11', 'page': 1.0, 'source': 'SPRi AI Brief_7월호_산업동향.pdf'}\n",
      "\n",
      "====================\n",
      "\n",
      "2. 기업/산업 \n",
      "   ▹ 구글, 멀티모달 AI 모델 ‘제미나이’ 공개············································································  3\n",
      "   ▹ 구글 클라우드, 기업용 AI 플랫폼에 이미지 생성 AI ‘이매진 2’ 추가  ·························  4\n",
      "   ▹ 앤스로픽, 20만 개의 토큰을 입력할 수 있는 ‘클로드 2.1’ 공개 ···································  5\n",
      "{'author': 'dj', 'context': '2. 기업/산업 \\n   ▹ 구글, 멀티모달 AI 모델 ‘제미나이’ 공개············································································  3\\n   ▹ 구글 클라우드, 기업용 AI 플랫폼에 이미지 생성 AI ‘이매진 2’ 추가  ·························  4\\n   ▹ 앤스로픽, 20만 개의 토큰을 입력할 수 있는 ‘클로드 2.1’ 공개 ···································  5', 'page': 1.0, 'source': 'SPRi AI Brief_2024년1월호_F.pdf'}\n",
      "\n",
      "====================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 실행 결과\n",
    "search_results = pinecone_retriever.invoke(\n",
    "    \"앤스로픽의 claude 출시 관련 내용을 알려줘\",\n",
    "    search_kwargs={\"filter\": {\"page\": {\"$lt\": 5}}, \"k\": 2},\n",
    ")\n",
    "for result in search_results:\n",
    "    print(result.page_content)\n",
    "    print(result.metadata)\n",
    "    print(\"\\n====================\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "동적 `search_kwargs` 사용\n",
    "- `filter`: metadata 필터링 적용\n",
    "\n",
    "(예시) `source` 가 `SPRi AI Brief_8월호_산업동향.pdf` 문서내 검색합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\n",
      "KEY Contents\n",
      "£ GPT-4o 미니, GPT-3.5 터보 대비 60% 이상 저렴하면서 성능은 우수\n",
      "n 오픈AI는 2024년 7월 28일 가장 비용 효율적인 소형 모델인 ‘GPT-4o 미니’를 출시하고 챗GPT에서 \n",
      "GPT-3.5를 대신해 무료 사용자 및 플러스와 팀 사용자에게 제공한다고 발표\n",
      "∙GPT-4o 미니는 입력 토큰 100만 개당 15센트, 출력 토큰 100만 개당 60센트로 가격이 책정되어, \n",
      "GPT-3.5 터보 대비 60% 이상 저렴\n",
      "{'author': 'dj', 'context': '앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\\nKEY Contents\\n£ GPT-4o 미니, GPT-3.5 터보 대비 60% 이상 저렴하면서 성능은 우수\\nn 오픈AI는 2024년 7월 28일 가장 비용 효율적인 소형 모델인 ‘GPT-4o 미니’를 출시하고 챗GPT에서 \\nGPT-3.5를 대신해 무료 사용자 및 플러스와 팀 사용자에게 제공한다고 발표\\n∙GPT-4o 미니는 입력 토큰 100만 개당 15센트, 출력 토큰 100만 개당 60센트로 가격이 책정되어, \\nGPT-3.5 터보 대비 60% 이상 저렴', 'page': 13.0, 'source': 'SPRi AI Brief_8월호_산업동향.pdf'}\n",
      "\n",
      "====================\n",
      "\n",
      "1. 정책/법제  \n",
      "2. 기업/산업 \n",
      "3. 기술/연구 \n",
      " 4. 인력/교육\n",
      "11\n",
      "오픈AI, 비용 효율적인 소형 AI 모델 ‘GPT-4o 미니’ 출시\n",
      "n 오픈AI가 GPT-3.5 터보 대비 60% 이상 저렴한 소형 모델 ‘GPT-4o’ 미니를 발표했으며, 저렴한 \n",
      "비용과 낮은 지연 시간으로 다양한 애플리케이션에 활용될 것으로 기대\n",
      "n GPT-4o는 주요 벤치마크에서 GPT-3.5를 앞섰으며, 경쟁 소형 모델인 구글의 제미나이 플래시와 \n",
      "앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\n",
      "KEY Contents\n",
      "{'author': 'dj', 'context': '1. 정책/법제  \\n2. 기업/산업 \\n3. 기술/연구 \\n 4. 인력/교육\\n11\\n오픈AI, 비용 효율적인 소형 AI 모델 ‘GPT-4o 미니’ 출시\\nn 오픈AI가 GPT-3.5 터보 대비 60% 이상 저렴한 소형 모델 ‘GPT-4o’ 미니를 발표했으며, 저렴한 \\n비용과 낮은 지연 시간으로 다양한 애플리케이션에 활용될 것으로 기대\\nn GPT-4o는 주요 벤치마크에서 GPT-3.5를 앞섰으며, 경쟁 소형 모델인 구글의 제미나이 플래시와 \\n앤트로픽의 클로드 하이쿠보다 높은 점수를 기록\\nKEY Contents', 'page': 13.0, 'source': 'SPRi AI Brief_8월호_산업동향.pdf'}\n",
      "\n",
      "====================\n",
      "\n",
      "KEY Contents\n",
      "£ 제미나이 1.5 플래시, GPT-3.5 터보 대비 속도 40% 향상 및 비용은 4배 저렴\n",
      "n 구글이 2024년 6월 28일 ‘제미나이 1.5 프로’ 모델의 컨텍스트 창을 200만 개 토큰으로 확장하는 \n",
      "한편, 제미나이 1.5 프로보다 속도를 개선한 ‘제미나이 1.5 플래시’를 정식 출시\n",
      "∙구글은 2024년 5월 I/O에서 대기자 명단을 받아 제미나이 1.5 프로에서 200만 개 토큰 컨텍스트 창*을 \n",
      "제공하다가 이번 발표로 모든 개발자로 대상을 확대\n",
      "{'author': 'dj', 'context': 'KEY Contents\\n£ 제미나이 1.5 플래시, GPT-3.5 터보 대비 속도 40% 향상 및 비용은 4배 저렴\\nn 구글이 2024년 6월 28일 ‘제미나이 1.5 프로’ 모델의 컨텍스트 창을 200만 개 토큰으로 확장하는 \\n한편, 제미나이 1.5 프로보다 속도를 개선한 ‘제미나이 1.5 플래시’를 정식 출시\\n∙구글은 2024년 5월 I/O에서 대기자 명단을 받아 제미나이 1.5 프로에서 200만 개 토큰 컨텍스트 창*을 \\n제공하다가 이번 발표로 모든 개발자로 대상을 확대', 'page': 12.0, 'source': 'SPRi AI Brief_8월호_산업동향.pdf'}\n",
      "\n",
      "====================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 실행 결과\n",
    "search_results = pinecone_retriever.invoke(\n",
    "    \"앤스로픽의 claude 3.5 출시 관련 내용을 알려줘\",\n",
    "    search_kwargs={\n",
    "        \"filter\": {\"source\": {\"$eq\": \"SPRi AI Brief_8월호_산업동향.pdf\"}},\n",
    "        \"k\": 3,\n",
    "    },\n",
    ")\n",
    "for result in search_results:\n",
    "    print(result.page_content)\n",
    "    print(result.metadata)\n",
    "    print(\"\\n====================\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reranking 적용\n",
    "\n",
    "- 동적 reranking 기능을 구현해 놓았지만, pinecone 라이브러리 의존성에 문제가 있을 수 있습니다.\n",
    "- 따라서, 아래 코드는 향후 의존성 해결 후 원활하게 동작할 수 있습니다.\n",
    "\n",
    "참고 문서: https://docs.pinecone.io/guides/inference/rerank"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# reranker 미사용\n",
    "retrieval_results = pinecone_retriever.invoke(\n",
    "    \"앤스로픽의 클로드 소넷\",\n",
    ")\n",
    "\n",
    "# BGE-reranker-v2-m3 모델 사용\n",
    "reranked_results = pinecone_retriever.invoke(\n",
    "    \"앤스로픽의 클로드 소넷\",\n",
    "    search_kwargs={\"rerank\": True, \"rerank_model\": \"bge-reranker-v2-m3\", \"top_n\": 3},\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Retrieval]\n",
      "1. 정책/법제  \n",
      "2. 기업/산업 \n",
      "3. 기술/연구 \n",
      " 4. 인력/교육\n",
      "9\n",
      "앤스로픽, 최신 AI 모델 ‘클로드 3.5 소네트’ 출시 \n",
      "n 앤스로픽이 최신 AI 모델 ‘클로드 3.5 소네트’을 공개하고 이전 모델 중 가장 고성능 모델인 \n",
      "‘클로드 3 오퍼스’나 오픈AI의 최신 모델 ‘GPT-4o’보다 성능이 뛰어나다고 강조\n",
      "n 앤스로픽은 클로드로 생성한 코딩이나 문서 등을 실시간으로 확인해 편집과 같은 작업을 할 수 \n",
      "있는 ‘아티팩트’ 신기능도 출시\n",
      "KEY Contents\n",
      "\n",
      "------------------\n",
      "\n",
      "[Reranked] rerank_score:  0.99635005\n",
      "1. 정책/법제  \n",
      "2. 기업/산업 \n",
      "3. 기술/연구 \n",
      " 4. 인력/교육\n",
      "9\n",
      "앤스로픽, 최신 AI 모델 ‘클로드 3.5 소네트’ 출시 \n",
      "n 앤스로픽이 최신 AI 모델 ‘클로드 3.5 소네트’을 공개하고 이전 모델 중 가장 고성능 모델인 \n",
      "‘클로드 3 오퍼스’나 오픈AI의 최신 모델 ‘GPT-4o’보다 성능이 뛰어나다고 강조\n",
      "n 앤스로픽은 클로드로 생성한 코딩이나 문서 등을 실시간으로 확인해 편집과 같은 작업을 할 수 \n",
      "있는 ‘아티팩트’ 신기능도 출시\n",
      "KEY Contents\n",
      "\n",
      "====================\n",
      "\n",
      "[Retrieval]\n",
      "▹ 앤스로픽, 최신 AI 모델 ‘클로드 3.5 소네트’ 출시··························································· 10\n",
      "   ▹ 프랑스의 미스트랄AI, 6억 유로 규모의 투자 유치  ························································ 11\n",
      "\n",
      "------------------\n",
      "\n",
      "[Reranked] rerank_score:  0.9956346\n",
      "있는 ‘아티팩트’ 신기능도 출시\n",
      "KEY Contents\n",
      "£ 클로드 3.5 소네트, 이전 대표모델 클로드 3 오퍼스와 오픈AI의 GPT-4o 능가\n",
      "n 앤스로픽이 2024년 6월 21일 ‘클로드(Claude) 3.5’ 모델군 중 첫 번째로 ‘소네트(Sonnet)’를 공개\n",
      "했으며, 하반기에 경량 모델 ‘하이쿠(Haiku)’와 가장 강력한 ‘오퍼스(Opus)’를 출시할 계획\n",
      "∙소네트는 클로드 웹사이트(Claude.ai) 및 iOS 앱에서 무료로 제공되며, 유료 가입자에게는 이용 \n",
      "한도를 대폭 넓혀서 제공\n",
      "\n",
      "====================\n",
      "\n",
      "[Retrieval]\n",
      "1. 정책/법제  \n",
      "2. 기업/산업 \n",
      "3. 기술/연구 \n",
      " 4. 인력/교육\n",
      "앤스로픽, 20만 개의 토큰을 입력할 수 있는 ‘클로드 2.1’ 공개  \n",
      "n 앤스로픽이 최대 20만 개의 토큰 입력을 지원하고 환각 현상을 두 배 줄인 ‘클로드 2.1’ 버전을 \n",
      "공개했으며, 20만 개의 토큰 입력은 유료 버전인 ‘클로드 프로’에서만 제공\n",
      "n 클로드 2.1은 베타 버전의 도구 기능을 도입하여, 사용자가 API를 연결하는 방식으로 복잡한 수치 \n",
      "추론을 위한 계산기 사용이나 웹 검색을 이용한 질의 답변 등 다양한 작업을 수행 가능하도록 지원\n",
      "\n",
      "------------------\n",
      "\n",
      "[Reranked] rerank_score:  0.94240075\n",
      "▹ 앤스로픽, 최신 AI 모델 ‘클로드 3.5 소네트’ 출시··························································· 10\n",
      "   ▹ 프랑스의 미스트랄AI, 6억 유로 규모의 투자 유치  ························································ 11\n",
      "\n",
      "====================\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# retrieval_results 와 reranked_results 를 비교합니다.\n",
    "for res1, res2 in zip(retrieval_results, reranked_results):\n",
    "    print(\"[Retrieval]\")\n",
    "    print(res1.page_content)\n",
    "    print(\"\\n------------------\\n\")\n",
    "    print(\"[Reranked] rerank_score: \", res2.metadata[\"rerank_score\"])\n",
    "    print(res2.page_content)\n",
    "    print(\"\\n====================\\n\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "seoulrnd-graphrag-gR8UbrDn-py3.11",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
